<!-- <script setup lang="ts">
import TheWelcome from '../components/TheWelcome.vue'
</script>

<template>
  <main>
    <TheWelcome />
  </main>
</template> -->
<template>
  <div>ref: {{ obj }}</div>
  <div>shallowRef: {{ obj2 }}</div>
  <div>customRef: {{ obj3 }}</div>
  <div ref="DOM">我是 dom</div>
  <hr />
  <button @click="change">修改name值</button>
</template>

<script setup lang="ts">
import {
  ref,
  isRef,
  shallowRef,
  triggerRef,
  customRef,
  onMounted,
  reactive,
  readonly,
  shallowReactive,
} from "vue";
/**
 * ref和reactive区别
 * 1. ref支持所有类型  reactive只支持引用类型(Array Object Map Set)
 * 2. ref.取值、赋值需要加.value，而reactive不需要
 * 3. reactive proxy 不能直接赋值 否则会破坏响应式对象
 * 4. shallowReactive和shallowRef 一样都只能在第一个属性这修改才是响应式的（都是浅层响应，都会被ref、reactive所影响）
 */

// reactive不能直接赋值的解决方案
let list1 = reactive<number[]>([1, 2, 3]); //此方法创建的不能直接赋值
const list2 = reactive<{ arr: number[] }>({ arr: [] }); //此方法创建的可以直接赋值
const a = readonly(list1); //此方法创建的值，为只读的，但是会受原来的值(list1)的影响
setTimeout(() => {
  list1 = [4, 5, 6];
  list2.arr = [123, 456];
  console.log(list1, list2);
  console.log(list1, a);
}, 1500);

// 直接定义的变量不具备vue的响应式
// const obj = { name: "小文" };
// ref具备深层次的响应(无论修改哪个值都会响应)，而shallowRef只是浅层次的响应(修改整个value才会响应)
// ref不能和shallowRef定义的值在一起，会影响shallowRef造成视图的更新(原因:ref更新调用了triggerRef,所以shallowRef会变)
// triggerRef会强制更新收集的依赖
const obj = ref({ name: "小文" });
const obj2 = shallowRef({ name: "小文2" });
function MyRef<T>(value: T) {
  let timer: any;
  return customRef((track, trigger) => {
    return {
      get() {
        track(); //收集依赖
        return value;
      },
      set(newValue) {
        clearTimeout(timer);
        timer = setTimeout(() => {
          value = newValue;
          timer = null;
          trigger(); //触发依赖
        }, 1000);
      },
    };
  });
}
const obj3 = MyRef<object>({ name: '"xiaoyi"' }); //obj3是一个ref对象
const change = () => {
  // obj.value.name = "小樟";   //不能和shallowRef定义的值在一起，会影响shallowRef造成视图的更新
  // obj2.value.name = "小樟2";
  // obj2.value = { name: "小樟2" };
  // triggerRef(obj2);
  obj3.value = { name: "xiaoyi2" };
  console.log(obj);
  // 判断是否为ref对象
  console.log(isRef(obj));
};
const DOM = ref<HTMLDivElement>(); // 这里定义一个和div中ref名字一样的变量名即可
onMounted(() => {
  console.log(DOM.value?.innerText);
});
</script>

<style lang="scss" scoped></style>
